#ifndef ALGEBRAICOPERATION_HPP
#define ALGEBRAICOPERATION_HPP
#include <QImage>
#include "Ptr.hpp"



using namespace OOPUtils;



class AlgebraicOperation
{

private:

	QString _operationName;

protected:

	virtual QRgb __doOperation (QRgb c1, QRgb c2)
	{
		double a1 = (double)qAlpha (c1) / 255;
		double a2 = (double)qAlpha (c2) / 255;
		return qRgba (a1 * qRed (c1) + (1.0 - a1) * a2 * qRed (c2),
				a1 * qGreen (c1) + (1.0 - a1) * a2 * qGreen (c2),
				a1 * qBlue (c1) + (1.0 - a1) * a2 * qBlue (c2),
				(1.0 - (1 - a1) * (1 - a2)) * 255);
	}

public:

	AlgebraicOperation (const QString & name = QString ("Normal"))
		: _operationName (name)
	{
		
	}

	const QString & getOperationName () const
	{
		return _operationName;
	}

	Ptr< QImage > process (Ptr< QImage > pImage1, Ptr< QImage > pImage2, 
			QRect region1, QRect region2, QPoint oImage1, QPoint oImage2,
			QSize resultImageSize)
	{
		Ptr< QImage > pResult = new QImage (resultImageSize,
			QImage::Format_ARGB32);
		int w = pImage2->width ();
		int h = pImage2->height ();
		for (int v = 0; v < pResult->height (); ++v)
		{
			QRgb * resultLine = (QRgb *)pResult->scanLine (v);
			bool isInImage1Height = true, isInImage2Height = true;
			QRgb * image1Line = 0, * image2Line = 0;
			if (v - oImage1.y () < 0 || 
					v - oImage1.y () >= region1.height ())
				isInImage1Height = false;
			else 
				image1Line = (QRgb *)pImage1->scanLine (
						v - oImage1.y () + region1.top ());
			if (v - oImage2.y () < 0 || 
					v - oImage2.y () >= region2.height ())
				isInImage2Height = false;
			else 
				image2Line = (QRgb *)pImage2->scanLine (
						v - oImage2.y () + region2.top ());
			QRgb * a = (QRgb *)pImage2->scanLine (0);
			for (int u = 0; u < pResult->width (); ++u) {
				bool isInImage1Width = true, isInImage2Width = true;
				if (isInImage1Height) {
					if (u - oImage1.x () < 0 ||
							u - oImage1.x () >= region1.width ())
						isInImage1Width = false;
				} else
					isInImage1Width = false;
				if (isInImage2Height) {
					if (u - oImage2.x () < 0 ||
							u - oImage2.x () >= region2.width ())
						isInImage2Width = false;
				} else
					isInImage2Width = false;
				QRgb pixel1, pixel2;
				if (isInImage1Width)
					pixel1 = image1Line[u - oImage1.x () + region1.left ()];
				else
					pixel1 = qRgba (0, 0, 0, 0);
				if (isInImage2Width)
					pixel2 = image2Line[u - oImage2.x () + region2.left ()];
				else
					pixel2 = qRgba (0, 0, 0, 0);
				resultLine[u] = __doOperation (pixel1, pixel2);
			}
		}
		return pResult;
	}



};

#endif // ALGEBRAICOPERATION_HPP
